﻿using D.WebApi.Core.MediatRUtils;
using D.WebApi.Core.Middlewares;
using D.WebApi.Core.Models;
using D.IdentityDbStore.Extensions;
using D.IdentityDbStore.Options;
using D.UtilCache;
using D.UtilConfiguration;
using D.UtilHangfire;
using D.UtilInterfaceDoc;
using D.UtilIoc;
using D.UtilNLog;
using D.UtilSqlsugarOrm;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SqlSugar;
using System.IO.Compression;
using System.Diagnostics;
using D.WebApi.Core.Dtos;
using D.WebApi.Core.Attributes;
using System.Reflection;
using IdentityServer4.Services;
using D.WebApi.Core.Filters;
using System;
using D.WebApi.Core.Routes;
using static System.Net.Mime.MediaTypeNames;

namespace D.WebApi.Core
{
    public static class BaseApi
    {
        /// <summary>
        /// 静态实例
        /// </summary>
        public static IServiceProvider instance { get; set; }

        /// <summary>
        /// 全局配置文件
        /// </summary>
        public static AppConfig appConfig { get; set; }

        /// <summary>
        /// 获取全部注释Xml文档
        /// </summary>
        public static List<string> XmlCommentsFilePath
        {
            get
            {
                var basePath = AppContext.BaseDirectory;
                DirectoryInfo d = new DirectoryInfo(basePath);
                FileInfo[] files = d.GetFiles("*.xml");
                var xmls = files.Select(a => Path.Combine(basePath, a.FullName)).ToList();
                return xmls;
            }
        }

        /// <summary>
        /// 全部控制器的权限列表
        /// </summary>
        public static List<PermissionDto> permissions = new List<PermissionDto>();

        /// <summary>
        /// 获取全部控制器中标识的模块权限集合
        /// </summary>
        private static void GetAppPermission()
        {
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                var types = assembly.GetTypes()
                    .Where(type => !type.IsAbstract)
                    .Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type)
                    || typeof(Microsoft.AspNetCore.Mvc.Controller).IsAssignableFrom(type)).ToList();

                types.ForEach(type =>
                {
                    var permissionGroup = type.GetCustomAttribute<PermissionGroupAttribute>();
                    foreach (var methodInfo in type.GetMethods())
                    {
                        var permissionAttr = methodInfo.GetCustomAttributes<PermissionAttribute>().FirstOrDefault();

                        if (permissionAttr is not null)
                        {
                            var permission = new PermissionDto
                            {
                                Group = permissionAttr.Group,
                                Name = permissionAttr.Name,
                                Description = permissionAttr.Description,
                                Sign = $"{type.Name}.{methodInfo.Name}".ToUpper().Replace("CONTROLLER", "")
                            };
                            if (string.IsNullOrEmpty(permission.Group))
                            {
                                if (permissionGroup is null)
                                {
                                    permissionGroup = new PermissionGroupAttribute(type.Name.Replace("Controller", ""));
                                };
                                permission.Group = permissionGroup.Name;
                            }
                            permissions.Add(permission);
                        }
                    }
                });
            }

            // 缓存
            var cache = instance.GetService<UtilCache.ICacheService>();
            if (cache != null && permissions.Count > 0)
            {
                cache.SetAsync("permissions", permissions);
            }
        }

        public static bool AddService(IServiceCollection services, IConfiguration configuration, IHostEnvironment environment)
        {
            UtilConsole.ConsoleUtil.Info("当前环境：" + environment.EnvironmentName);

            // 添加自动加载配置文件
            configuration.AddConfigureFiles(environment);

            // 获取全局配置文件内容
            appConfig = configuration.Get<AppConfig>();
            if (appConfig == null || appConfig.DbConfig == null)
            {
                UtilConsole.ConsoleUtil.Err("加载配置文件失败");
                return false;
            }

            // 网站应用进行了负载均衡或者挂了CDN，获取IP地址
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardLimit = null;// 限制所处理的标头中的条目数
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; // X-Forwarded-For：保存代理链中关于发起请求的客户端和后续代理的信息。X-Forwarded-Proto：原方案的值 (HTTP/HTTPS)    
                options.KnownNetworks.Clear(); // 从中接受转接头的已知网络的地址范围。 使用无类别域际路由选择 (CIDR) 表示法提供 IP 范围。使用CDN时应清空
                options.KnownProxies.Clear(); // 从中接受转接头的已知代理的地址。 使用 KnownProxies 指定精确的 IP 地址匹配。使用CDN时应清空
            });

            #region 后台返回给前端的数据进行数据压缩
            services.Configure<BrotliCompressionProviderOptions>(options =>
            {
                options.Level = CompressionLevel.Optimal;
            }).Configure<GzipCompressionProviderOptions>(options =>
            {
                options.Level = CompressionLevel.Optimal;
            }).AddResponseCompression(options =>
            {
                options.EnableForHttps = true;
                options.Providers.Add<BrotliCompressionProvider>();
                options.Providers.Add<GzipCompressionProvider>();
                options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
                {
                "text/html; charset=utf-8",
                "application/xhtml+xml",
                "application/atom+xml",
                "image/svg+xml",
                "application/javascript",
                "application/json",
                "application/xml",
                "text/css",
                "text/html",
                "text/json",
                "text/plain",
                "text/xml"
                });
            });
            #endregion

            //指定程序集
            services.AddMediaRs();

            // 自动化注入仓储和服务
            services.AddAutoScanInjection();

            // AutoMapper 自动映射
            //services.AddAutoMapper();

            // 上下文
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            // NLog 日志
            services.AddNLogUtil();

            if (appConfig.StartRedisCache)
            {
                if (appConfig.RedisConfig == null)
                {
                    UtilConsole.ConsoleUtil.Err("redis 配置文件加载失败");
                    return false;
                }
                if (appConfig.RedisConfig.Ip == null)
                {
                    UtilConsole.ConsoleUtil.Err("redis 配置文件IP地址加载失败");
                    return false;
                }
                if (appConfig.RedisConfig.Port == null)
                {
                    UtilConsole.ConsoleUtil.Err("redis 配置文件Port地址加载失败");
                    return false;
                }
                // 开启Redis
                services.AddRedis(appConfig.RedisConfig.Ip, appConfig.RedisConfig.Port, appConfig.RedisConfig.Pwd, appConfig.RedisConfig.DefaultDatabase);
            }
            else
            {
                // 缓存
                services.AddMemory();
            }

            // Cors 跨域
            services.AddCors(o =>
            {//CORS Cross-Origin-Resource-Sharing 跨域:跨源资源共享（同源策略） 

                //if (urls.Length > 0)
                //{
                //    o.AddPolicy(policyName, policy =>
                //    {
                //        policy.WithOrigins(urls.Split(','))
                //              .AllowAnyHeader()
                //              .AllowAnyMethod();
                //    });
                //}
                //else
                //{
                UtilConsole.ConsoleUtil.Info("允许任意跨域请求：Limit");
                //允许任意跨域请求
                o.AddPolicy("Limit", policy =>
                {
                    policy.SetIsOriginAllowed((host) => true)
                            .AllowAnyOrigin()
                            .AllowAnyHeader()
                            .AllowAnyMethod();
                });

                //}
            });

            // Swagger UI
            if (environment.IsDevelopment())
            {
                //获取应用程序所在目录（绝对，不受工作目录影响，建议采用此方法获取路径）
                var basePath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
                if (basePath != null)
                {
                    UtilConsole.ConsoleUtil.Waring("放开接口API文档有风险");
                    services.AddApieDoc(basePath, XmlCommentsFilePath);
                }
            }

            // 自动任务
            services.AddHangfire();

            // 启动数据库
            services.AddSqlSugar(appConfig.DbConfig);

            // 控制器
            services.AddControllers(options =>
            {
                // 全局异常过滤
                //options.Filters.Add<ExceptionMiddleware>();

                // 增加路由统一前缀
                if (!string.IsNullOrWhiteSpace(appConfig.SiteConfig.RoutePrefix))
                {
                    //参考：https://gist.github.com/itavero/2b40dfb476bebff756da35b5c7ff7384
                    //https://www.strathweb.com/2016/06/global-route-prefix-with-asp-net-core-mvc-revisited/
                    //https://benjii.me/2016/08/global-routes-for-asp-net-core-mvc/
                    options.Conventions.Insert(0, new GlobalRoutePrefixConvention(appConfig.SiteConfig.RoutePrefix));
                }

                // 接口性能监控过滤器
                options.Filters.Add(typeof(ExtBenchmarkActionUtilFilter));
            });
               //.AddNewtonsoftJson(options =>
               // {// 注册 Json 序列化配置
               //     // 序列化时key为驼峰样式，首字母小写    
               //     options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
               //     options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
               //     // 设置时间格式
               //     options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
               //     // 忽略循环引用
               //     options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
               // });

            #region Ids4 

            services.AddIdentityServer(o =>
            {
                //o.IssuerUri = ServerUrl;
                //o.PublicOrigin = ServerUrl;
                //o.Discovery.ShowApiScopes = true;
                //o.Discovery.ShowClaims = true;
                o.Events.RaiseErrorEvents = true;
                o.Events.RaiseFailureEvents = true;
                o.Events.RaiseInformationEvents = true;
                o.Events.RaiseSuccessEvents = true;
            })
            //创建一个用于对token签名的临时密钥材料xx.rsa(但是在生产环境中应该使用可持久的密钥材料):
            //.AddDeveloperSigningCredential()
            //添加来自数据库（客户机、资源、CORS）的配置数据
            .AddDbStore(new DbStoreOptions()
            {
                ConnectionString = appConfig.DbConfig.ConnectionString,
                DbType = SqlSugarOrm.GetDbType(appConfig.DbConfig.DbType),

                EnableTokenCleanup = appConfig.IdentityServerStoreOptions.EnableTokenCleanup,
                TokenCleanupInterval = appConfig.IdentityServerStoreOptions.TokenCleanupInterval,
                TokenCleanupBatchSize = appConfig.IdentityServerStoreOptions.TokenCleanupBatchSize,
            });

            //services.AddIdentity<SysUserEntity, IdentityRole>(o =>
            //{
            //    //密码不需要数字
            //    o.Password.RequireDigit = false;
            //    //密码不区分小写
            //    o.Password.RequireLowercase = false;
            //    //密码不区分大写
            //    o.Password.RequireUppercase = false;
            //    //密码不需要字母数字
            //    o.Password.RequireNonAlphanumeric = false;
            //    //密码长度至少6位
            //    o.Password.RequiredLength = 6;
            //});

            //.AddInMemoryIdentityResources(Config.GetIdentityResources())
            //.AddInMemoryApiResources(Config.GetApis())
            //.AddInMemoryClients(Config.GetClients(WebHostEnvironment.IsProduction()))
            //.AddProfileService<CustomProfileService>()

            #endregion



            // 加载https
            //builder.WebHost.UseKestrel(options =>
            //{
            //    options.Listen(IPAddress.Any, 5000,
            //     listenOptions =>
            //     {
            //         //参数为证书文件名称，证书密码
            //         listenOptions.UseHttps("fullchain.pfx");
            //         listenOptions.UseHttps("fullchainapi.pfx");
            //     });
            //});

            //if (!builder.Environment.IsDevelopment())
            //{
            //    builder.Services.AddHttpsRedirection(options =>
            //    {
            //        options.RedirectStatusCode = (int)HttpStatusCode.PermanentRedirect;
            //        options.HttpsPort = 5000;
            //    });
            //}
            return true;
        }

        public static void UseApp(WebApplication app, IHostEnvironment environment)
        {
            #region 异常

            if (environment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseExceptionHandler(builder =>
                {
                    builder.Run(async context =>
                    {
                        var exceptionHandlerPathFeature = context.Features.Get<Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature>();
                        if (exceptionHandlerPathFeature != null)
                        {
                            await context.Response.WriteAsync($"error:{exceptionHandlerPathFeature.Error.Message}");
                        }
                    });
                });
            }
            #endregion

            #region 网站应用进行了负载均衡或者挂了CDN，获取IP地址
            // 转发请求头和证书
            app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.All }).UseCertificateForwarding();

            //为了获得真实IP地址
            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            }).UseCertificateForwarding();

            #endregion

            //app.UseStaticFiles();//启动www静态目录
            //启动上传文件目录
            //app.UseStaticFiles(new StaticFileOptions
            //{
            //    FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(builder.Configuration.GetValue<string>("UploadConfig:UploadDir")),
            //    RequestPath = "/upload/view"
            //});
            //app.UseHttpsRedirection(); //开启Https重定向
            //app.UseCookiePolicy();//Cookie策略

            app.UseMiddleware<ExceptionMiddleware>();// 异常中间件
            app.UseResponseCompression();// 后台返回给前端的数据进行数据压缩
            app.UseHangfire();// 定时任务
            app.UseRouting();// 路由
            app.UseCors("Limit");// 跨域
            app.UseAuthorization();// 授权
            app.UseAuthentication();// 鉴权
            app.UseIdentityServer();// ids4

            if (environment.IsDevelopment())
            { // Api文档
              //app.UseMySwagger();
                app.UseMyKnife4j();
            }

            #region 配置端点

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();

                endpoints.MapControllerRoute(
                  name: "areas",
                  pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
                );
            });
            #endregion

            instance = app.Services;

            // 加载权限
            GetAppPermission();

            //var hostEnvironment = instance.GetRequiredService<IHostEnvironment>();
            appConfig.SiteConfig.ApplicationName = app.Environment.ApplicationName;

            ThreadPool.GetMinThreads(out int work, out int comple);
            ThreadPool.GetAvailableThreads(out int worktemp, out int completemp);
            UtilConsole.ConsoleUtil.Info($"[{DateTime.Now:HH:mm:ss} 核心数为：{Environment.ProcessorCount}--默认线程最小为：{work}--Available:{worktemp}");

            // 开启自动任务
            //RecurringJob.AddOrUpdate(() => UtilConsole.ConsoleUtil.Info("你好"), "*/5 * * * * ?");
            //RecurringJob.AddOrUpdate<IAutoCleanAssignTotalCountTask>((job) => job.CleanAssignTotalCountAsync(), "*/2 * * * * ?");
            //RecurringJob.AddOrUpdate<IAutoCleanAssignTotalCountTask>((job) => job.CleanAssignTotalCountAsync(), "0 0 1 * * ?", TimeZoneInfo.Local);// 每天1点00分开始执行，当前时区
        }
    }
}